package org.oimwrapper.scheduledtasks;


import Thor.API.tcMetaDataSet;
import Thor.API.tcResultSet;
import com.thortech.xl.dataaccess.tcDataSet;
import java.util.*;
import java.sql.*;

import java.sql.ResultSet;
import org.oimwrapper.connectors.OIMTaskBase;
import org.oimwrapper.connectors.exceptions.OIMMissingAttributeException;
import org.oimwrapper.connectors.genericdb.OIMQueryProcessor;
import org.oimwrapper.oimutils.StringUtils;



//import com.davita.oimutils.db.DBReconUtils;

public class LoadLookupFromDb extends OIMTaskBase {
    
    private String jdbcResourceName;
    private String tableName;
    private String keyField;
    private String valueField;
    private String combineDecode;
    private boolean bcombineDecode;
    private String lookupTable;
    private Hashtable jdbcAttributes;
    private String dbType;
   
    private String where;
    
    private String sql;
    

    
    private boolean stop = false;

    public boolean stop() {
        stop = true;
        return stop;
    }

    public LoadLookupFromDb() {
        super("OIM.LOADLOOKUPFROMDB");
    }
    
    public boolean doInit()
    {
        boolean isValid = true;
        try {
            lookupTable = this.getCriticalAttribute("lookupTable");
            dbType = this.getAttribute("dbType");
            keyField = this.getCriticalAttribute("keyField");
            valueField = this.getCriticalAttribute("valueField");
            tableName = this.getCriticalAttribute("tableName");
            sql = "SELECT " + keyField + "," + valueField + " FROM " + tableName + " ";
            
            if (dbType != null && dbType.equalsIgnoreCase("external"))
            {
                jdbcResourceName = this.getCriticalAttribute("jdbcResourceName");
            }
            
        } catch (OIMMissingAttributeException ex) {
            logger.error("Missing Attribute " + ex.getMessage());
            return false;
        }
        
        bcombineDecode = this.getBooleanAttribute("combineDecode",false);
        where = this.getAttribute("where");
        
        if (!StringUtils.isEmpty(where))
            sql = sql + where;
        return true;
        
    }
    
    public void execute()
    {
        
        if (!doInit())
        {
            logger.error("Init Failed");
            return;
        }
        
        if (dbType != null && dbType.equalsIgnoreCase("external"))
            loadFromExternalDb();
        else
            loadFromInternalDb();
        

    }

    private void loadFromInternalDb() {
        
        logger.info("Starting Internal Load");
        logger.info("Reading DB " + sql);
        HashMap lookupMap = new HashMap();
        
        try {
            tcDataSet dataSet = new tcDataSet();
            dataSet.setQuery(this.getDataBase(), sql);
            dataSet.executeQuery();
            tcResultSet results = new tcMetaDataSet(dataSet.getDataSetData(), this.getDataBase());
            for (int i = 0; i < results.getRowCount(); i++) {
                if (bcombineDecode) {
                    String comb = (String) results.getStringValue(keyField) + "-" + (String) results.getStringValue(valueField);
                    lookupMap.put(results.getStringValue(keyField), comb);
                } else {
                    lookupMap.put(results.getStringValue(keyField), results.getStringValue(valueField));
                }

            }
        } catch (Exception e) {
            logger.error("APIError",e);
            return;
        }
        
        //logger.debug("Internal Lookup:" + lookupMap);
        try
        {
            int loadcount = importLookup(lookupMap);
            logger.info("Load Completed. total records loaded " + loadcount);
        }
        catch(Exception e)
        {
            logger.error("APIError",e);
        }
    }
    
    private void loadFromExternalDb()
    {
        logger.info("Starting External Load");
        logger.info("Reading DB " + sql);
        Statement stmt = null;
        ResultSet rs = null;
        HashMap lookupMap = new HashMap();

        OIMQueryProcessor qp = new OIMQueryProcessor();
        qp.setKeyField(keyField);

        try
        {
            qp.openConnection(getITResData(this.jdbcResourceName));
            Map records = qp.runQuery(sql);
            if (records != null && records.size() > 0)
            {
                logger.debug("HAVE RECORDS");
                Set keySet = records.keySet();
                Iterator i = keySet.iterator();
                while(i.hasNext())
                {
                    String key = (String)i.next();
                    //logger.debug("Key " + key);
                    if (StringUtils.isEmpty(key))
                        continue;
                    List dataList = (List)records.get(key);
                    if (dataList == null || dataList.size() == 0)
                        continue;
                    Map dataMap = (Map)dataList.get(0);
                    if (dataMap == null || dataMap.size() == 0)
                        continue;
                    //logger.debug("KEY " + key + " DATA " + dataMap);
                    
                    if (bcombineDecode)
                    {
                        String comb = (String)dataMap.get(keyField) + "-" + (String)dataMap.get(valueField);
                        lookupMap.put(dataMap.get(keyField),comb);
                    }
                    else
                        lookupMap.put(dataMap.get(keyField),dataMap.get(valueField));
                    
                }
                
            }
        }
        catch(Exception e)
        {
            logger.error("Error Running Query " + e.getMessage(),e);
            return;
        }
        
        
        try
        {
            int loadcount = importLookup(lookupMap);
            logger.info("Load Completed. total records loaded " + loadcount);
        }
        catch(Exception e)
        {
            logger.error("APIError",e);
        }
    }
    
    private int importLookup(HashMap lookupMap) throws Exception
    {
        if(lookupMap == null || lookupMap.size() == 0)
        {
            logger.error("No Records Found to Import");
            return 0;
        }
        
        int loadcount = 0;
        boolean cleared = true;
        try
        {
            this.clearLookup(lookupTable);

        } catch (Exception ex)
        {
            logger.error("Error Clearing Lookup " + lookupTable);
            cleared = false;
        }

        if (!cleared)
        {
            try {
                this.createLookup(lookupTable);
            } catch (Exception ex) {
                logger.error("Error Creating Lookup " + lookupTable,ex);
                throw new Exception("Error Creating Lookup " + lookupTable,ex);
            }
        }
        
        try
        {
            Set keyset = lookupMap.keySet();
            Iterator i = keyset.iterator();
            loadcount = 0;
            while(i.hasNext())
            {
                String key = (String)i.next();
                String val = (String)lookupMap.get(key);
                this.addLookupValue(key,val,lookupTable);
                loadcount++;
            }
            

        } catch (Exception ex)
        {
            logger.error("Error Adding Lookup Entries " + lookupTable);
        }

        return loadcount;
    }
    
}
